#pragma once
#include "gtest/gtest.h"

#include "Utility/FileSystem/SGFileSystem.h"

#include "DataStructure/Common/Validation.h"
#include "DataStructure/Input/Solver/Project.h"

#include "DBManager/IService/Input/Constraint/ISUPORTService.h"
#include "DBManager/IService/Input/Dynamic/IEIGRLService.h"
#include "DBManager/IService/Input/Dynamic/ISPECSELService.h"
// #include "DBManager/IService/Input/Element/IElementSummaryService.h"
#include "DBManager/IService/Input/Element/IElementService.h"
#include "DBManager/IService/Input/Parameter/IHYBDAMPService.h"
#include "DBManager/IService/Input/Table/ITABDMP1Service.h"
#include "DBManager/IService/Input/Table/ITABLED1Service.h"
#include "SGFem/ElementCalculator/Factory/ElementCalculatorFactory.h"
#include "DBManager/IService/Input/Parameter/IParameterService.h"

#include "SGFem/Task/Kernel/MModel.h"
#include "SGFem/Task/Kernel/ResponseSpectrumAnalysisTask.h"

#include "SGFem/Constraint/RElement/BoundaryCondition.h"

using SG::DataStructure::FEM::Project;
using SG::FEMSolver::Element::ElementCalculatorFactory;
TEST (ResponseSpectrumAnalysisTaskTest, ResponseSpectrumCalculatorTest)
{
    // 读取模型数据
    Project project;
    project.m_modelFilePath = SG::Utility::FileSystem::getTestDataPath ("SGFem/ModalAnalysis/");
    project.m_modelFileName = "Casestudy_apply_spectra_abs.bdf";
    project.m_jobName       = "Casestudy_apply_spectra_abs_Result";
    project.m_workSpace     = ".";

    // 导入数据库
    DB_SERVICEFACTORY->ClearDatabase ();
    SG::Import::SGImporter importer (DB_SERVICEFACTORY);
    auto                   status = importer.Import (project.m_modelFilePath + project.m_modelFileName);
    ASSERT_EQ (status, Status::STATUS_Success);

    // 初始化
    auto    subcaseIds = DB_SERVICEFACTORY->get<ISubcaseService> ()->GetAllSubcaseID ();
    auto    subcaseId  = subcaseIds[0];
    auto    para       = DB_SERVICEFACTORY->get<ISubcaseService> ()->FindSubCase (subcaseId);
    Subcase subcase (para);
    auto&   assembly = SG::FEMSolver::AssemblyEigen::GetInstance ();
    assembly.Clear ();
    assembly.Initialize (DB_SERVICEFACTORY, subcase, { 1 });  // 完成节点和自由度排序。开辟整体矩阵及向量的存储空间
    assembly.ActiveMassMatrix ();

    Kernel::MModel           ModelTest (SG::DataStructure::FEM::SOLType::SOL_SEDCEIG, DB_SERVICEFACTORY);
    ModelTest.Initialize (subcaseIds);
    ModelTest.CalcMatrixEquation (subcaseId);
     auto& coordHandler = SG::FEMSolver::CoordinateProcessor::GetInstance ();
     coordHandler.Initialize (DB_SERVICEFACTORY);              // 初始化，计算所有局部坐标系的基矢量和全局坐标系
    // AnalysisProcess::RegisterElementCalculator ();            // 注册单元类型

    // 静力分析，计算每个单元的刚度阵和质量阵并组装
    const auto elementTypes = DB_SERVICEFACTORY->get<IElementService> ()->GetAllElementTypes ();  // 获取模型单元类型
    for (const auto& type : elementTypes)
    {
        auto eleCalculator = SG::FEMSolver::Element::ElementCalculatorFactory::Create (type);
        if (NULL == eleCalculator)
        {
            std::cout << "can 't find element calc " << std::endl;
        }

        eleCalculator->Initialize (type);
        eleCalculator->ComputeElementMatries (DB_SERVICEFACTORY);
    }
    std::cout << "== compute stiffness finish" << std::endl;

    // 约束处理
    SG::FEMSolver::Constraint::BoundaryCondition::ComputeControlMatrix (DB_SERVICEFACTORY, subcase);
    assembly.Assembly (DB_SERVICEFACTORY);
    std::cout << "== assembly finish" << std::endl;

    
    // Kernel::MModel           ModelTest (SG::DataStructure::FEM::AnalysisTypes::ANALYSISTYPE_Modes, DB_SERVICEFACTORY);
    SG::Utility::SGParameter myParameter;


    // Test data
    // 模态分析
    SG::DataStructure::FEM::EIGRLData EIGRLData;
    ASSERT_EQ (Status::STATUS_Success, DB_SERVICEFACTORY->get<IEIGRLService> ()->FindBySId (subcase.GetMethodId (), EIGRLData));
    int ModesOrder = EIGRLData.m_ND;  // 求解阶数

    // 模态分析
    SG::DataStructure::FEM::SPECSELData SPECSELData;
    ASSERT_EQ (Status::STATUS_Success, DB_SERVICEFACTORY->get<ISPECSELService> ()->FindById (0, SPECSELData));

    for (const auto& spec_item : SPECSELData.m_TABLESList)
    {
        // const int tid = static_cast<int>(tid_double); // 将 double 类型的 ID 转换为整数
        const int tid = static_cast<int>(spec_item.m_TID);
        SG::DataStructure::FEM::TABLED1Data tableD1Data;


        if (DB_SERVICEFACTORY->get<SG::DBManager::ITABLED1Service>()->FindById(tid, tableD1Data) == SG::DataStructure::Common::Status::STATUS_Success)
        {
            std::ostringstream freq_ss;
            std::ostringstream accel_ss;
            
            freq_ss << std::scientific << std::setprecision(15);
            accel_ss << std::scientific << std::setprecision(15);

            bool isFirst = true;
            for (const auto& point : tableD1Data.m_XYList)
            {
                if (!isFirst) {
                    freq_ss << " ";  
                    accel_ss << " ";
                }
                freq_ss << point.m_X;  
                accel_ss << point.m_Y; 
                isFirst = false;
            }

            myParameter.AddString("TABLED1_FREQUENCIES_" + std::to_string(tid), freq_ss.str());
            myParameter.AddString("TABLED1_VALUES_" + std::to_string(tid), accel_ss.str());
        }
        else
        {
            std::cerr << "警告: 在数据库中未找到 ID 为 " << tid << " 的 TABLED1 数据。" << std::endl;
        }
    }



    // int ModesOrder = EIGRLData.m_ND;  // 求解阶数
    SG::DataStructure::FEM::SUPORTData SUPORTData;
    DB_SERVICEFACTORY->get<ISUPORTService> ()->FindById (57, SUPORTData);


    SG::DataStructure::FEM::TABDMP1Data TABDMP1Data;
    DB_SERVICEFACTORY->get<ITABDMP1Service> ()->FindById (200, TABDMP1Data);
    
    SG::Utility::SGParameter Parameter = DB_SERVICEFACTORY->get<IParameterService> ()->GetSolverParameter ();
    std::string combinationMethod = "DEFAULT";  // 设置一个字符串默认值

    if (Parameter.Has ("OPTION") && Parameter["OPTION"].IsString ())
    {
        combinationMethod = Parameter["OPTION"].GetString ();
    }

    myParameter.AddInt ("SUPORT_C", SUPORTData.m_C);
    myParameter.AddInt ("SUPORT_ID", SUPORTData.m_id);
    myParameter.AddInt ("SubcaseID", subcaseId);
    myParameter.AddInt ("ModesOrder", ModesOrder);
    myParameter.AddString ("FrequencySelectionMode", "LM");          //"LM"：低频优先，"SM"：高频优先
    myParameter.AddString ("combinationMethod", combinationMethod);  

    Kernel::ResponseSpectrumAnalysisTask calc (ModelTest, myParameter, SPECSELData, TABDMP1Data);
    calc.Solve ();
    // //输出h5
    // std::string h5path = project.m_jobName + ".h5";
    // SGInfo << "OutPut H5 Result:" << h5path;
    // SG::Export::NH5Export::WriterNastranHDF5 (DB_SERVICEFACTORY, project, h5path);

    // 输出结果矩阵，3行ModesOrder列
    std::vector<std::vector<Real>> modalTest (3, std::vector<Real> (18, 0.0));

        SG::Algebra::Vec_t Disp;
        SG::Algebra::Vec_t Vel;
        SG::Algebra::Vec_t Acc;
        ModelTest.GetDisplacement (subcaseId, 0, _OUT Disp);
        ModelTest.GetVelocity (subcaseId, 0, _OUT Vel);
        ModelTest.GetAcceleration (subcaseId, 0, _OUT Acc);



modalTest[0].resize(Disp.size());
memcpy(modalTest[0].data(), Disp.data(), Disp.size() * sizeof(double));
modalTest[1].resize(Vel.size());
memcpy(modalTest[1].data(), Vel.data(), Vel.size() * sizeof(double));

modalTest[2].resize(Acc.size());
memcpy(modalTest[2].data(), Acc.data(), Acc.size() * sizeof(double));


    // Target data
    std::vector<std::vector<Real>> modalTarget (3, std::vector<Real> (18, 0.0));
modalTarget[0] = {
        8.633339637882588E-18,3.5687012978746155E-14,3.2286654856937623E-17,1.0515544081112874E-8,3.1302472979994676E-8,5.213244511313482E-8,1.2599372236359107E-13,3.570056239191732E-14,7.601338178348159E-14,3.443816203541198E-8,3.1302472979994676E-8,6.907548977490367E-8,1.6464975653053486E-13,0.0,0.0,0.0,0.0,0.0,
    };
    modalTarget[1] = {
        1.0127134767969799E-13,3.823922322490201E-10,3.468302867823121E-13,1.53421510148571E-4,4.5670225317476394E-4,6.42894746943498E-4,1.349143430393929E-9,3.825383486557313E-10,8.137268385302479E-10,3.751451435266319E-4,4.5670225317476394E-4,8.518355397001351E-4,1.7625493458792365E-9,0.0,0.0,0.0,0.0,0.0,
};
    modalTarget[2] = {
       1.3042702704409202E-9,4.107058629458923E-6,3.780724291851525E-9,2.552781714551481,7.599072382980012,8.88155320181886,1.4464462312511147E-5,4.108658088020515E-6,8.721487968483446E-6,4.278548207982407,7.599072382980012,11.768057992409995,1.8895041491540463E-5,0.0,0.0,0.0,0.0,0.0,
    };




for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 18; ++j)
    {
                ASSERT_NEAR (modalTest[i][j], modalTarget[i][j], 1e-1)
        // EXPECT_TRUE(SG::DataStructure::Common::isNear(modalTest[i][j], modalTarget[i][j],tolerance))
            << "isNear check failed at index [" << i << "][" << j << "]\n"
            << "  modalTest[" << i << "][" << j << "] = " << modalTest[i][j] << "\n"
            << "  modalTarget[" << i << "][" << j << "] = " << modalTarget[i][j];
    }
}
}